﻿using AMapPlugin;
using IM.Easy.Core.AppContext;
using IM.Easy.Core.Extensions;
using IM.Easy.Core.Services;
using IM.Easy.Entity.Log;
using IM.Easy.Infrastructure.Query;
using IM.Easy.LogServices.Dtos;
using IM.Easy.LogServices.IServices;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IM.Easy.LogServices.Services
{
    /// <summary>
    /// 请求追踪服务
    /// </summary>
    public class RequestTrackingService : AppServices<RequestTrackingLog>, IRequestTrackingService
    {
        private readonly IAmapPlugin _amapPlugin;
        public RequestTrackingService(ISqlSugarClient db, IAmapPlugin amapPlugin) : base(db)
        {
            _amapPlugin = amapPlugin;
        }
        ///// <summary>
        ///// 记录当前请求追踪信息
        ///// </summary>
        ///// <returns></returns>
        //public async Task<RequestTrackingLog> LogTracking()
        //{
        //    var log = GetCurrentInfo();
        //    //log.ResponseBody = await context.GetResponseBody();

        //    Db.Insertable(log).ExecuteCommand();
        //    return log;
        //}

        /// <summary>
        /// 获取当前的追踪日志
        /// </summary>
        /// <returns></returns>
        public RequestTrackingLog GetCurrentInfo()
        {
            var context = ImApp.Current;
            //var remoteInfo = context.GetRemoteIpInfo();
            var clientIP = context.GetClientUserIp();
            var remoteInfo = _amapPlugin.GetIpInfo(clientIP).GetAwaiter().GetResult();
            var address = $"{remoteInfo.Province}{remoteInfo.City}";
            var log = new RequestTrackingLog
            {
                RequestTime = DateTime.Now,       // 当前请求时间
                HttpMethod = context.Request.Method, // HTTP请求方法
                Url = context.Request.Path,           // 请求的完整URL
                ClientIP = clientIP,
                //UserId = context.User?.Identity?.Name ?? "Anonymous",
                UserId = ImApp.User.Id,
                UserAgent = context.GetUserAgent(),
                TraceIdentifier = context.TraceIdentifier,
                Address = address,
                CreatedAt = DateTime.Now,
            };
            return log;
        }

        public PageResponse<RequestTrackingLog> GetPageList(RequestTrackingLogQueryDto query)
        {
            var queryable = Context.Queryable<RequestTrackingLog>();
            var exp = Expressionable.Create<RequestTrackingLog>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.UserName), s => s.UserName.Contains(query.UserName))
                  .AndIF(query.BeginRequestTime.HasValue, s => s.RequestTime.Value >= query.BeginRequestTime)
                  .AndIF(query.EndRequestTime.HasValue, s => s.RequestTime.Value <= query.EndRequestTime)
                  .AndIF(!string.IsNullOrEmpty(query.TraceIdentifier), s => s.TraceIdentifier == query.TraceIdentifier);
            
            var page = queryable
                 .Where(exp.ToExpression())
                 .ToPageList<RequestTrackingLog, RequestTrackingLog>(query);
            return page;
        }

        public bool Delete(params Guid[] Id)
        {
            // TODO: 添加删除逻辑
            return Context.Deleteable<RequestTrackingLog>(Id).ExecuteCommandHasChange();
        }

        /// <summary>
        /// 获取操作统计
        /// </summary>
        /// <returns></returns>
        public List<OperationChartData> GetDateData(RequestTrackingLogQueryDto query)
        {
            //默认统计近一周内数据
            var end = query.EndRequestTime.HasValue ? query.EndRequestTime.Value.Date : DateTime.Now.AddDays(1).Date;
            var start = query.BeginRequestTime.HasValue ? query.BeginRequestTime.Value.Date : end.AddDays(-7);

            var aggregatedData = Context.Queryable<RequestTrackingLog>()
                .Where(it => it.CreatedAt >= start && it.CreatedAt < end)
                .GroupBy(it => it.CreatedAt.Value.Date)
                .Select(it => new
                {
                    Date = it.CreatedAt.Value.Date,
                    Frequency = SqlFunc.AggregateCount(it.Id),
                    Visitor = SqlFunc.AggregateDistinctCount(it.ClientIP),
                })
                .ToList();

            var totalDays = (end - start).Days;
            var fullDates = Enumerable.Range(0, totalDays)
                .Select(offset => start.AddDays(offset))
                .ToList();

            var result = (from date in fullDates
                          join agg in aggregatedData
                            on date.ToString("yyyy-MM-dd") equals agg.Date.ToString("yyyy-MM-dd") into gj
                          from sub in gj.DefaultIfEmpty()
                          orderby date
                          select new OperationChartData
                          {
                              Date = date.ToString("yyyy-MM-dd"),
                              Frequency = sub?.Frequency ?? 0,
                              Visitor = sub?.Visitor ?? 0,
                          }).ToList();
            return result;

        }
    }
}
